package assignment;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.io.*;
import java.util.*;
import javax.swing.*;

public class Assignment3 {

	String[] uniqueWords;
	int[] counts;
	String[] stopWords = { "at", "but", "that", "on", "off" };

	private String wordHandler(String word) {
		int startIndex = -1;
		int endIndex = -1;
		char[] a = word.toCharArray();
		// Find out letter start index
		for (int i = 0; i < a.length; i++) {
			if (Character.isLetter(a[i])) {
				startIndex = i;
				break;
			}
		}
		// Find out letter end index
		for (int i = a.length - 1; i >= 0; i--) {
			if (Character.isLetter(a[i])) {
				endIndex = i;
				break;
			}
		}

		// Filter the "stop words"
		String s = word.substring(startIndex, endIndex + 1);
		for (String compare : stopWords) {
			if (compare.equals(s))
				return null;
		}

		return s;
	}

	/**
	 * Get the word list form a file.
	 * 
	 * @param filename
	 * @return
	 * @throws IOException
	 */
	private String[] getWordsFromFile(String filename) throws IOException {
		// Load the file
		File file = new File(filename);
		// Create File Reader
		BufferedReader reader = new BufferedReader(new FileReader(file));
		// Read line in file
		String s = reader.readLine();
		// This is the word list, we will add word to it.
		ArrayList<String> slist = new ArrayList<String>();
		// Read line till the end of the file
		while (s != null) {
			// User space as the splitter to split the line to word
			String[] t = s.split("\\s");
			for (String word : t) {
				// If word is not null or empty, add it to list.
				String processedWord = wordHandler(word);
				if (processedWord != null && !processedWord.isEmpty())
					slist.add(processedWord);
			}
			// Read next line
			s = reader.readLine();
		}
		reader.close();
		// Convert list to string array, sort it and return it.
		String[] rs = slist.toArray(new String[0]);
		Arrays.sort(rs);
		return rs;
	}

	/**
	 * This method sets String[] uniqueWords property and int[] counts property
	 * 
	 * @param allWords
	 */
	private void setUniqueAndCounts(String[] allWords) {
		// Advanced one
		// 'HashSet' class does not allow duplicated memeber.
		HashSet<String> unique = new HashSet<String>();
		for (String s : allWords)
			unique.add(s);
		uniqueWords = unique.toArray(new String[0]);
		Arrays.sort(uniqueWords);

		// Set Counts
		counts = new int[uniqueWords.length];
		for (int i = 0; i < uniqueWords.length; i++) {
			// Local count as the word appearing frequency.
			int localCount = 0;
			for (String w : allWords) {
				if (uniqueWords[i].equals(w))
					localCount++;
			}
			counts[i] = localCount;
		}
	}

	/**
	 * Display all the words on the wall.
	 * 
	 */
	private void displayWords() {
		// Create a frame
		JFrame frame = new JFrame();
		frame.setSize(400, 200);
		frame.setTitle("Word Cloud");
		frame.setLayout(new FlowLayout());
		frame.setVisible(true);
		for (int i = 0; i < uniqueWords.length; i++) {
			// Create label for each word.
			JLabel label = new JLabel(uniqueWords[i]);
			// Set font size
			// Random for the font style
			Random random = new Random();
			Font font = new Font("sans-serif", (random.nextInt(2 - 0) + 0),
					counts[i] * 10);
			label.setFont(font);
			// Random color
			Color color = new Color((random.nextInt(255 - 0) + 0),
					(random.nextInt(255 - 0) + 0),
					(random.nextInt(255 - 0) + 0));
			label.setForeground(color);
			frame.add(label);
		}

	}

	/**
	 * Call makeCloud to make the word cloud
	 * 
	 * @param filename
	 * @throws IOException
	 */
	public void makeCloud(String filename) throws IOException {
		setUniqueAndCounts(getWordsFromFile(filename));
		displayWords();
	}

	public static void main(String[] args) {
		Assignment3 a3 = new Assignment3();
		try {
			a3.makeCloud("F:\\KnockKnock.txt");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
